package _hash

import org.junit.Assert
import org.junit.Test

/*
https://leetcode.cn/problems/happy-number/description/
https://programmercarl.com/0202.%E5%BF%AB%E4%B9%90%E6%95%B0.html

题型：哈希法

  202. 快乐数
  编写一个算法来判断一个数 n 是不是快乐数。

  「快乐数」 定义为：

  对于一个正整数，每一次将该数替换为它每个位置上的数字的平方和。
  然后重复这个过程直到这个数变为 1，也可能是 无限循环 但始终变不到 1。
  如果这个过程 结果为 1，那么这个数就是快乐数。
  如果 n 是 快乐数 就返回 true ；不是，则返回 false 。

  示例 1：

    输入：n = 19
    输出：true
    解释：
    12 + 92 = 82
    82 + 22 = 68
    62 + 82 = 100
    12 + 02 + 02 = 1

示例 2：
    输入：n = 2
    输出：false
 */
class leetcode_202_Kotlin {
    @Test
    fun test_1() {
        val actual = isHappy(19)
        val expected = true
        Assert.assertEquals(expected, actual)
    }

    @Test
    fun test_2() {
        val actual = isHappy(2)
        val expected = false
        Assert.assertEquals(expected, actual)
    }


    private fun isHappy(n: Int): Boolean {
        /**
         * 题型：哈希法
         *
         * 思路：
         * 循环逻辑：把n存入HashSet，然后计算 n，直到n 为 1， 或者 无限循环，n 已经被包含了
         * 循环结束后，若n == 1，说明是一个快乐数
         *
         */
        val set = HashSet<Int>()
        var n: Int = n
        // 结束条件：n 为 1， 或者 无限循环，n 已经被包含了
        while (n != 1 && !set.contains(n)) {
            // TODO()
            set.add(n)
            n = sum(n)
        }
        return n == 1
    }

    private fun sum(n: Int): Int {
        /**
        n = 19
        -------
        19 % 10 = 9  => 9 * 9
        19 / 10 = 1
        -------
        1 % 10 = 1  => 1 * 1
        1 / 10 = 0

         */
        var sum: Int = 0
        var n: Int = n
        while (n > 0) {
            val tmp = n % 10
            sum = sum + tmp * tmp
            n = n / 10
        }
        return sum
    }
}